package com.zhtd.knockerdemo;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;

import com.zhtd.knocker.business.LoginService;
import com.zhtd.knocker.business.entity.BaseEntity;
import com.zhtd.knocker.business.entity.HostRequest;
import com.zhtd.knocker.business.entity.HostResponse;
import com.zhtd.knocker.business.entity.LoginCallback;
import com.zhtd.knocker.business.entity.LoginRequest;
import com.zhtd.knocker.business.entity.LoginResponse;
import com.zhtd.knocker.business.entity.QueryHostCallback;
import com.zhtd.knocker.util.GsonUtils;

import java.lang.ref.WeakReference;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    ProgressBar pb;
    Button syncLogin;
    Button asyncLogin;

    Button syncHost;
    Button asyncHost;
    Button multiLogin;

    TextView tvLogin;
    TextView tvHost;
    final MyHandler handler = new MyHandler(this);

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        pb = (ProgressBar) findViewById(R.id.pb);
        syncLogin = (Button) findViewById(R.id.btn_sync);
        asyncLogin = (Button) findViewById(R.id.btn_async);
        syncHost = (Button) findViewById(R.id.btn_sync_host);
        asyncHost = (Button) findViewById(R.id.btn_async_host);
        multiLogin = (Button) findViewById(R.id.btn_mutli_login);
        tvLogin = (TextView) findViewById(R.id.tv_login);
        tvHost = (TextView) findViewById(R.id.tv_host);
        syncLogin.setOnClickListener(this);
        asyncLogin.setOnClickListener(this);
        syncHost.setOnClickListener(this);
        asyncHost.setOnClickListener(this);
        multiLogin.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v == syncLogin) {
            syncLogin();
        } else if (v == asyncLogin) {
            asyncLogin();
        } else if (v == syncHost) {
            syncQueryHost();
        } else if (v == asyncHost) {
            asyncQueryHost();
        } else if (v == multiLogin) {
            multiLogin();
        }
    }

    private void queryHostSuccess(HostResponse res) {
        tvHost.setText("查询主机成功\r\n" + GsonUtils.toJSON(res));
        pb.setVisibility(View.GONE);
    }

    private void queryHostFailed(String msg) {
        tvHost.setText("查询主机失败：" + msg);
        pb.setVisibility(View.GONE);
    }

    private void loginSuccess(BaseEntity<LoginResponse> loginRes) {
        tvLogin.setText("登录成功\r\n" + GsonUtils.toJSON(loginRes));
        pb.setVisibility(View.GONE);
    }

    private void loginFailed(String msg) {
        tvLogin.setText("登录失败：" + msg);
        pb.setVisibility(View.GONE);
    }

    private void clearStatusLogin() {
        tvLogin.setText("");
        pb.setIndeterminate(true);
        pb.setVisibility(View.VISIBLE);
    }

    private void clearStatusHost() {
        tvHost.setText("");
        pb.setIndeterminate(true);
        pb.setVisibility(View.VISIBLE);
    }

    static class MyHandler extends Handler {
        WeakReference<MainActivity> wr;

        public MyHandler(MainActivity act) {
            wr = new WeakReference<>(act);
        }

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (wr.get().isFinishing()) {
                return;
            }
            if (msg.what == 1) {
                wr.get().loginSuccess((BaseEntity<LoginResponse>) msg.obj);
            } else if (msg.what == 2) {
                wr.get().loginFailed(msg.obj.toString());
            } else if (msg.what == 3) {
                wr.get().queryHostSuccess((HostResponse) msg.obj);
            } else if (msg.what == 4) {
                wr.get().queryHostFailed(msg.obj.toString());
            } else if (msg.what == 5) {
                wr.get().multiFinished();
            }
        }
    }

    ;

    private void asyncLogin() {
        clearStatusLogin();
        LoginRequest req = new LoginRequest("yx", "0b82a7c1ad82c6280c00e30b81be916d");
        String url = "http://x01.ngrok.groupinno.com/api/v2/user/login";
        LoginService.asyncLogin(req, url, new LCB(this));
    }

    public static class LCB implements LoginCallback {

        WeakReference<MainActivity> ma;

        public LCB(MainActivity m) {
            ma = new WeakReference<>(m);
        }

        @Override
        public void onFailed(String msg) {
            ma.get().loginFailed(msg);
        }

        @Override
        public void onSuccessLogin(BaseEntity<LoginResponse> loginRes) {
            ma.get().loginSuccess(loginRes);
        }

    }

    private void syncLogin() {
        clearStatusLogin();
        new Thread("syncLogin") {
            @Override
            public void run() {
                super.run();
                LoginRequest req = new LoginRequest("yx", "0b82a7c1ad82c6280c00e30b81be916d");
                String url = "http://x01.ngrok.groupinno.com/api/v2/user/login";
                Message msg = Message.obtain();
                try {
                    BaseEntity<LoginResponse> loginRes = LoginService.login(req, url);
                    msg.what = 1;
                    msg.obj = loginRes;
                } catch (Exception e) {
                    final String value = e.getMessage();
                    msg.what = 2;
                    msg.obj = value;
                }
                handler.sendMessage(msg);
            }
        }.start();
    }

    final int count = 10;
    final LinkedBlockingQueue<BaseEntity<LoginResponse>> rightList = new LinkedBlockingQueue<>();
    final LinkedBlockingQueue<String> errorList = new LinkedBlockingQueue<>();
    CountDownLatch cdl;
    ExecutorService service;
    long start = 0;

    private void multiLoginExecutor() {
        clearStatusLogin();
        rightList.clear();
        errorList.clear();
        cdl = new CountDownLatch(count);
        service = Executors.newCachedThreadPool();
        Task task = new Task(this);
        start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            service.execute(task);
        }
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    cdl.await();
                    Message msg = Message.obtain();
                    msg.what = 5;
                    handler.sendMessage(msg);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void multiLogin() {
        clearStatusLogin();
        rightList.clear();
        errorList.clear();
        cdl = new CountDownLatch(count);
        Task task = new Task(this);
        start = System.currentTimeMillis();
        for (int i = 0; i < count; i++) {
            new Thread(task).start();
        }
        new Thread() {
            @Override
            public void run() {
                super.run();
                try {
                    cdl.await();
                    Message msg = Message.obtain();
                    msg.what = 5;
                    handler.sendMessage(msg);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();
    }

    private void multiFinished() {
        pb.setVisibility(View.GONE);
        long end = System.currentTimeMillis();
        tvLogin.setText(String.format("finisehd:%d,error:%d", rightList.size(), errorList.size()));
        tvLogin.append(String.format("\r\ntime=%d", end - start));
        if (service != null && !service.isTerminated()) {
            service.shutdown();
        }
    }

    static class Task implements Runnable {
        WeakReference<MainActivity> wr;

        public Task(MainActivity act) {
            wr = new WeakReference<>(act);
        }

        @Override
        public void run() {
            if (wr.get().isFinishing()) {
                return;
            }
            LoginRequest req = new LoginRequest("yx", "0b82a7c1ad82c6280c00e30b81be916d");
            String url = "http://x01.ngrok.groupinno.com/api/v2/user/login";
            try {
                BaseEntity<LoginResponse> loginRes = LoginService.login(req, url);
                wr.get().rightList.put(loginRes);
            } catch (Exception e) {
                try {
                    wr.get().errorList.put(e.getMessage());
                } catch (InterruptedException e1) {
                }
            }
            wr.get().cdl.countDown();
        }
    }

    public static class QCB implements QueryHostCallback {

        WeakReference<MainActivity> ma;

        public QCB(MainActivity m) {
            ma = new WeakReference<>(m);
        }

        @Override
        public void onSuccessQueryHost(HostResponse host) {
            ma.get().queryHostSuccess(host);
        }

        @Override
        public void onFailed(String msg) {
            ma.get().loginFailed(msg);
        }
    }

    private void asyncQueryHost() {
        clearStatusHost();
        HostRequest req = new HostRequest("yx", "0b82a7c1ad82c6280c00e30b81be916d");
        String url = "http://rms.groupinno.com/api/register/loginurl";
        LoginService.asyncQueryHost(req, url, new QCB(this));
    }

    private void syncQueryHost() {
        clearStatusHost();
        new Thread("syncLogin") {
            @Override
            public void run() {
                super.run();
                HostRequest req = new HostRequest("yx", "0b82a7c1ad82c6280c00e30b81be916d");
                String url = "http://rms.groupinno.com/api/register/loginurl";
                Message msg = Message.obtain();
                try {
                    HostResponse queryHostRes = LoginService.queryHost(req, url);
                    msg.what = 3;
                    msg.obj = queryHostRes;
                } catch (Exception e) {
                    final String value = e.getMessage();
                    msg.what = 4;
                    msg.obj = value;
                }
                handler.sendMessage(msg);
            }
        }.start();
    }

    @Override
    protected void onStop() {
        super.onStop();
        LoginService.release();
    }
}
